import { compileToFunction } from "./compiler"
import { callHook, mountComponent } from "./initLifeCycle"
import { initState } from "./initState"
import { nextTick } from "./nextTick"
import Watcher from "./observe/watcher"
import { mergeOptions } from "./utils"

export function initMixin(Vue) {
  Vue.prototype._init = function (options) {
    const vm = this
    vm.$options = mergeOptions(this.constructor.options, options)

    callHook(vm, "beforeCreate")
    initState(vm) // 创建应用实例
    callHook(vm, "created")

    if (options.el) {
      vm.$mount(options.el) // 挂载应用实例
    }
  }

  Vue.prototype.$mount = function (el) {
    const vm = this
    el = document.querySelector(el)
    let ops = vm.$options

    if (!ops.render) {
      let template
      if (!ops.template && el) {
        template = el.outerHTML
      } else {
        template = ops.template
      }
      if (template) {
        // 编译成render函数
        ops.render = compileToFunction(template)
      }
    }

    // 开始挂载组件
    mountComponent(vm, el)
  }

  Vue.prototype.$nextTick = nextTick

  Vue.prototype.$watch = function (exprOrFn, cb) {
    new Watcher(this, exprOrFn, { user: true }, cb)
  }
}
